@include "globals.awk"
@include "readcsv.awk"
@include "dist.awk"
@include "lib.awk"

BEGIN { srand(Seed  ? Seed : 1)
        print "Seed=" , Seed
        main() }

function main(   w,gp,np,hi,lo,rows,all,d,ps) {
    readcsv(w,gp,np,hi,lo,rows,all,d)
    projects(w,gp,np,hi,lo,rows,all,d,ps)
    normalize(ps)
    for(i in all)
	knn(all[i],ps,w,gp,np,hi,lo,rows,all,d)
}
#XXX summing across all
function knn(row1,ps,w,gp,np,hi,lo,rows,all,d,	\
	     klass,p,one,two,n,row2,w,ws,sum) {
    klass = klass1(gp)
    for(p in ps) {
	one = ps[p]["<"]
	two = ps[p][">"]
	if (one == row1) continue
	if (two == row1) continue
	n    = length(ps[p]["="])
	row2 = closest(ps,p,one,two,n,w,gp,np,hi,lo,d)
	w    = ps[p]["x"]
	ws  += w
	sum += w*d[row2][klass]
    }
    return sum/(ws + 0.0001)
    # XXX must esnure at least two projections
}
function closest(ps,p,one,two,n,w,gp,np,hi,lo,d,\
		 a,b,c,x,j,k) {   
    a = dist(row,one,w,gp,np,hi,lo,d)
    b = dist(row,two,w,gp,np,hi,lo,d)
    c = ps[p]["c"]
    x = (a^2+c^2 - b^2)/(2*c + 0.00001)
    j = place(x,ps[p]["="])
    k = nextdoor(x,j,n,ps[p]["="])
    return ps[p]["="][k]["="]
}
function nextdoor(x,j,n,a,			\
		  i,k,ix,kx) {
    if (j == 1) return 2
    if (j == n) return n - 1
    i = j - 1
    k = j + 1
    ix = abs(x - a[i]["x"])
    kx = abs(x - a[k]["x"])
    if (ix < kx) k = i
    return k
}

function place(goal,a,  lo,hi,mid,here) {
    lo = 1; hi = length(a)
    while(max >= min) {
	mid  = int((lo + hi)/2)
	here = a[mid]["x"]
	if (here < goal)      lo = mid + 1
	else if (here > goal) hi = mid - 1
	else return mid }
}
function projects(w,gp,np,hi,lo,rows,all,d,ps,	\
		  min,repeats,err,p,r,i,n,more,atMost) {
    min  = 10^32
    p   = 1
    more = Enough
    atMost = TooMuch
    while(1) {
	if (more < 1)    break
        if (--atMost < 1) break
	say(".")
	err = project(ps,p,min,w,gp,np,hi,lo,rows,all,d)
	if (err >= min) 
	    delete ps[p]
	else {
            asort(ps[p]["="],ps[p]["="],"xsort")
	    more--
            p++
	    print (min=err) " rnn"  }}
}
function normalize(ps,     n,worst,i) {
    n = asort(ps,ps,"xsort")
    worst = ps[n]["x"]
    for(i=n;i>=1;i--) 
	ps[i]["x"] = worst/ps[i]["x"]

}
function project(ps,p,min,w,gp,np,hi,lo,rows,all,d,\
                 one,two,i,x,y,a,b,c,row,err,m,n) {
    m    = length(all)
    one  = anybut(all)
    two  = anybut(all,one)
    c = dist(one,two,w,gp,np,hi,lo,d)
    ps[p]["id"]=p
    ps[p]["<"]=one
    ps[p][">"]=two
    ps[p]["c"]=c
    for(i in all) {
        row = all[i]
	if (row==avoid) {continue}
	if (row == one ) {
	    a=x=0; b = c
        } else {
	    if (row == two) { 
		a=x=c;  b = 0
	    } else {
		a = dist(row,one,w,gp,np,hi,lo,d)
		b = dist(row,two,w,gp,np,hi,lo,d)
		x = (a^2+c^2 - b^2)/(2*c + 0.00001);  
	    }}	   
	y = sqrt(abs(a^2 - x^2))
        err += y
	ps[p]["x"] = err/m
	ps[p]["="][i]["x"] = x 
	ps[p]["="][i]["="] = i
        if (Prune) {
	    n++
	    if (n > Sampleth && n > m/Sampleth)
		if (err/n > min) 
		    return 10^32 }}
    return err/m
}
function rnn(id,a,r,    i,j,k,b,n,right,left) {
    n=asort(a,b,"xsort") 
    r[2]++
    r[n-1]++
    for(j=2;j<n;j++) {
       i = j-1
       k = j+1
       r[k] += 0; r[i] += 0; r[j] += 0
       left = b[j]["x"] - b[i]["x"]
       right= b[k]["x"] - b[j]["x"]
       if      (left > right)  { r[k]++ }
       else if (left < right)  { r[i]++ }
       else                    { r[k]++; r[i]++ }
    }
}
